// Package article
/**
* @Project : geektime-basic-go-study
* @File    : article.go
* @IDE     : GoLand
* @Author  : Tvux
* @Date    : 2024/11/9 08:50
**/

package article

import (
	"fmt"
	"geektime-basic-go-study/webook/backend/internal/domain"
	"geektime-basic-go-study/webook/backend/internal/service"
	"geektime-basic-go-study/webook/backend/internal/web"
	ijwt "geektime-basic-go-study/webook/backend/internal/web/jwt"
	"github.com/HJH0924/GenericGo/logger"
	"github.com/gin-gonic/gin"
	"net/http"
)

var _ web.Handler = (*Handler)(nil)

type Handler struct {
	articleSvc service.ArticleService
	logger.Logger
}

func NewHandler(articleSvc service.ArticleService, zl logger.Logger) *Handler {
	return &Handler{
		articleSvc: articleSvc,
		Logger:     zl,
	}
}

func (Self *Handler) RegisterRoutes(server *gin.Engine) {
	ag := server.Group("/articles")
	ag.POST("/edit", Self.Edit)
	ag.POST("/publish", Self.Publish)
}

func (Self *Handler) Publish(ctx *gin.Context) {
	var req articleReq
	if err := ctx.BindJSON(&req); err != nil {
		return
	}

	// TODO 校验输入

	claims, _ := ctx.Get("UserClaims")
	// 这里是肯定可以get到的，所以不需要判断是否get到
	userClaims, ok := claims.(*ijwt.UserClaims)
	if !ok {
		// 在日志中包含更多的上下文信息，例如原始的 claims 值和类型
		Self.Debug("article.Handler.Edit: Failed to parse UserClaims",
			logger.Field{Key: "success", Val: ok},                             // 记录ok的值
			logger.Field{Key: "claimsType", Val: fmt.Sprintf("%T", claims)},   // 包含 claims 的类型
			logger.Field{Key: "claimsValue", Val: fmt.Sprintf("%+v", claims)}, // 包含 claims 的值
			logger.Field{Key: "context", Val: ctx.Request.Context()},          // 记录请求的上下文
		)
		ctx.JSON(http.StatusOK, web.Result{Code: web.ServerErrNum, Msg: "系统错误"})
		return
	}
	aid, err := Self.articleSvc.Publish(ctx, req.toDomain(userClaims.Uid))

	if err != nil {
		Self.Debug("article.Handler.Publish Publish Failed", logger.ErrorField(err))
		ctx.JSON(http.StatusOK, web.Result{
			Code: web.ServerErrNum,
			Msg:  "系统错误",
		})
	}

	ctx.JSON(http.StatusOK, web.Result{
		Msg:  "success",
		Data: aid,
	})
}

func (Self *Handler) Edit(ctx *gin.Context) {
	var req articleReq
	if err := ctx.BindJSON(&req); err != nil {
		return
	}

	// TODO 校验输入

	claims, _ := ctx.Get("UserClaims")
	// 这里是肯定可以get到的，所以不需要判断是否get到
	userClaims, ok := claims.(*ijwt.UserClaims)
	if !ok {
		// 在日志中包含更多的上下文信息，例如原始的 claims 值和类型
		Self.Debug("article.Handler.Edit: Failed to parse UserClaims",
			logger.Field{Key: "success", Val: ok},                             // 记录ok的值
			logger.Field{Key: "claimsType", Val: fmt.Sprintf("%T", claims)},   // 包含 claims 的类型
			logger.Field{Key: "claimsValue", Val: fmt.Sprintf("%+v", claims)}, // 包含 claims 的值
			logger.Field{Key: "context", Val: ctx.Request.Context()},          // 记录请求的上下文
		)
		ctx.JSON(http.StatusOK, web.Result{Code: web.ServerErrNum, Msg: "系统错误"})
		return
	}

	aid, err := Self.articleSvc.CreateOrUpdate(ctx, req.toDomain(userClaims.Uid))

	if err != nil {
		Self.Debug("article.Handler.Edit CreateOrUpdate Failed", logger.ErrorField(err))
		ctx.JSON(http.StatusOK, web.Result{
			Code: web.ServerErrNum,
			Msg:  "系统错误",
		})
	}

	ctx.JSON(http.StatusOK, web.Result{
		Msg:  "success",
		Data: aid,
	})
}

type articleReq struct {
	Id      int64  `json:"id"`
	Title   string `json:"title"`
	Content string `json:"content"`
}

func (Self articleReq) toDomain(uid int64) domain.Article {
	return domain.Article{
		Id:      Self.Id,
		Title:   Self.Title,
		Content: Self.Content,
		Author:  domain.Author{Id: uid},
	}
}
